// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init()
db = cloud.database({
	throwOnNotFound: false
})

function randomWord(randomFlag, min, max){
	var str = "",
	  range = min,
	  arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z','_','-','='];
	// 随机产生
	if(randomFlag){
	  range = Math.round(Math.random() * (max-min)) + min;
	}
	for(var i=0; i<range; i++){
	  pos = Math.round(Math.random() * (arr.length-1));
	  str += arr[pos];
	}
	return str;
  }
function checkIDCard(idcode) {
	// 加权因子
	var weight_factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
	// 校验码
	var check_code = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];

	var code = idcode + "";
	var last = idcode[17]; //最后一位

	var seventeen = code.substring(0, 17);

	// ISO 7064:1983.MOD 11-2
	// 判断最后一位校验码是否正确
	var arr = seventeen.split("");
	var len = arr.length;
	var num = 0;
	for (var i = 0; i < len; i++) {
		num = num + arr[i] * weight_factor[i];
	}

	// 获取余数
	var resisue = num % 11;
	var last_no = check_code[resisue];

	var idcard_patter = /^[1-9][0-9]{5}([1][9][0-9]{2}|[2][0][0|1][0-9])([0][1-9]|[1][0|1|2])([0][1-9]|[1|2][0-9]|[3][0|1])[0-9]{3}([0-9]|[X])$/;

	// 判断格式是否正确
	var format = idcard_patter.test(idcode);

	// 返回验证结果，校验码和格式同时正确才算是合法的身份证号码
	return last === last_no && format ? true : false;
}
// 云函数入口函数
exports.main = async (event, context) => {
	const wxContext = cloud.getWXContext()
	console.log(event)
	try {
		const transaction = await db.startTransaction()
		let timeline = await transaction.collection('timeline').doc(event._id).get()
		console.log(timeline)
		let data = {
			openid:wxContext.OPENID,
			shop_id:timeline.data.shop_id,
			product_id:timeline.data.product_id,
			daily_id:timeline.data.daily_id,
			timeline_id:timeline.data._id,
			name:event.name,
			idcard:event.idcard,
			phone:event.phone,
			create_time:new Date(),
			type:event.type,
		}
		//校验姓名
		if(!data.name){
			throw ({
				msg: '请输入姓名',
				code: 10009
			})
		}
		//校验身份证号
		if(!data.idcard){
			throw ({
				msg: '请输入身份证号',
				code: 10010
			})
		}
		if(!checkIDCard(data.idcard)){
			throw ({
				msg: '身份证号格式不正确',
				code: 10011
			})
		}
		//校验联系电话
		if(!data.phone){
			throw ({
				msg: '请输入联系电话',
				code: 10012
			})
		}
		if (!timeline.data) throw({
			msg: '未找到对应的时间段',
			code: 10002
		})
		let shop = await db.collection('shop').doc(timeline.data.shop_id).field({
			status: true,
			is_visit: true
		}).get()
		if (!shop.data || shop.data.status != 2 || !shop.data.is_visit) {
			throw({
				msg: '门店不存在或未上线',
				code: 10003
			})
		}
		//获取product
		let product = await db.collection('product').doc(timeline.data.product_id).field({
			code_id: true,
			to_home: true,
			to_shop: true
		}).get()

		if (!product.data) {
			throw({
				msg: '产品不存在',
				code: 10001
			})
		}
		//获取daily
		let daily = await db.collection('daily').doc(timeline.data.daily_id).field({
			is_allow: true,
			time_begin: true,
			time_end: true,
			type: true,
			date:true
		}).get()
		//判断daily is_allow
		if (!daily.data || !daily.data.is_allow) {
			throw({
				msg: '当前日期不可预约',
				code: 10004
			})
		}
		//判断时间
		let date = (new Date).getTime()
		if (date < daily.data.time_begin.getTime()) {
			throw({
				msg: '预约未开始',
				code: 10005
			})
		}
		if (date > daily.data.time_end.getTime()) {
			throw({
				msg: '预约已结束',
				code: 10006
			})
		}
		//判断是否还有名额
		if (daily.data.type == 2 && timeline.data.nums_limit) {
			if (timeline.data.nums_max <= timeline.data.nums_cnt) {
				throw({
					msg: '来晚一步，已被预约完了！',
					code: 10007
				})
			}
		}
		const _ = db.command
		let today = new Date(daily.data.date)
		today.setMinutes(today.getMinutes()-480-today.getTimezoneOffset())
		console.log(today)
		//校验code
		data.appoint_date = today.getTime()
		if (product.data.code_id) {
			let code = await db.collection('code').doc(product.data.code_id).get()
			if (code.data) {
				data.code_id = code.data._id
				let appointed = await db.collection('appoint').where({
					idcard: data.idcard,
					code_id: product.data.code_id,
					status: _.in([1, 2, 5, 7]),
					appoint_date:_.gt(today.getTime()-86400*code.data.interval*1000)
				}).count()
				if(appointed.total>=code.data.times){
					throw({
						msg:'您在'+code.data.interval+'天内仅可预约'+code.data.times+'次',
						code: 10008
					})
				}
			}
		}
		
		//判断是否需要地址
		if((event.type=='to_home'||!product.data.to_shop)&&product.data.to_home){
			data.type = 'to_home'
			data.address = event.address
			if(!data.address){
				throw({
					msg:'请选择地址',
					code:10013
				})
			}
		}else{
			data.type = 'to_shop'
		}
		if(daily.data.type==1){
			data.status = 1
			data.randkey = randomWord(false,32)
		}else{
			data.status = 2
		}
		//写入表
		let add = await transaction.collection('appoint').add({data})
		//更新cnt
		await transaction.collection('timeline').doc(event._id).update({
			data:{nums_cnt:_.inc(1)}
		})
		//提交事务
		await transaction.commit()
		if(daily.data.type==1){
			return {
				code: 200,
				data:add._id,
				msg:'预约已提交'
			}
		}else{
			return {
				code: 200,
				data:add._id,
				msg:'预约成功'
			}
		}
		
	} catch (e) {
		console.error(`transaction error`, e)

		return e
	}
}